package com.tich.program.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.toolkit.Db;
import com.tich.constant.ExceptionConstant;
import com.tich.constant.RabbitMqConstant;
import com.tich.exception.*;
import com.tich.program.domain.dto.ProgramTicketUpdateDTO;
import com.tich.program.domain.dto.ProgramTicketsSaveDTO;
import com.tich.program.domain.entity.Program;
import com.tich.program.domain.entity.ProgramTicket;
import com.tich.program.domain.entity.TicketCategory;
import com.tich.program.domain.vo.ProgramTicketSelectVO;
import com.tich.program.mapper.ProgramTicketMapper;
import com.tich.program.service.IProgramTicketService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tich.utils.IdGeneratorUtil;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;

@Service
public class ProgramTicketServiceImpl extends ServiceImpl<ProgramTicketMapper, ProgramTicket> implements IProgramTicketService {

    @Autowired
    private ProgramTicketMapper programTicketMapper;
    @Autowired
    private RabbitTemplate rabbitTemplate;

    /**
     * 批量给节目添加门票
     * @param programTicketsSaveDTO
     * */
    public void saveProgramTickets(ProgramTicketsSaveDTO programTicketsSaveDTO) {
        //先查找是否有该节目，不存在的话直接抛出异常
        Long programId = programTicketsSaveDTO.getProgramId();
        if(!Db.lambdaQuery(Program.class).eq(Program::getId, programId).exists()){
            throw new ProgramNotFoundException(ExceptionConstant.PROGRAM_NOT_FOUND);
        }
        //补充节目门票实体类，插入数据库
        List<ProgramTicket> programTickets = programTicketsSaveDTO.getProgramTickets();
        programTickets.forEach(programTicket -> {
            //查找该门票类型是否存在，不存在的话抛出异常
            if(!Db.lambdaQuery(TicketCategory.class).eq(TicketCategory::getId, programTicket.getCategoryId()).exists()){
                throw new TicketCategoryNotFoundException(ExceptionConstant.TICKET_CATEGORY_NOT_FOUND);
            }
            programTicket.setProgramId(programId);
            programTicket.setId(IdGeneratorUtil.getInstance().nextId());
        });
        programTicketMapper.insert(programTickets);
    }

    /**
     * 根据节目id查询节目门票信息
     * @param programId
     * @return
     * */
    public List<ProgramTicketSelectVO> selectProgramTickets(Long programId) {
        //先查找是否有该节目，不存在的话直接抛出异常
        if(!Db.lambdaQuery(Program.class).eq(Program::getId, programId).exists()){
            throw new ProgramNotFoundException(ExceptionConstant.PROGRAM_NOT_FOUND);
        }
        return programTicketMapper.selectProgramTickets(programId);
    }

    /**
     * 修改节目门票信息
     * @param programTicketUpdateDTO
     * */
    public void updateProgramTicket(ProgramTicketUpdateDTO programTicketUpdateDTO) {
        //查询该门票是否存在
        ProgramTicket programTicket = programTicketMapper.selectById(programTicketUpdateDTO.getId());
        //不存在则抛出异常
        if(BeanUtil.isEmpty(programTicket)){
            throw new ProgramTicketNotFoundException(ExceptionConstant.PROGRAM_TICKET_NOT_FOUND);
        }
        //已开始则禁止修改
        if(programTicket.getRemainingCount().intValue() != programTicket.getTotalCount().intValue()){
            throw new ProgramTicketSellingRejectUpdateException(ExceptionConstant.PROGRAM_TICKET_SELLING_REJECT_UPDATE);
        }
        //修改价格小于0则抛出异常
        if(programTicket.getPrice() <= 0){
            throw new ProgramTicketPriceLessZeroException(ExceptionConstant.PROGRAM_TICKET_PRICE_LESS_ZERO);
        }
        ProgramTicket programTicketUpdate = BeanUtil.copyProperties(programTicketUpdateDTO, ProgramTicket.class);
        //同步将剩余票数修改
        programTicketUpdate.setRemainingCount(programTicketUpdate.getTotalCount());
        programTicketUpdate.setUpdateTime(LocalDateTime.now());
        programTicketMapper.updateById(programTicketUpdate);
    }

    /**
     * 根据id删除门票
     * @param id
     * */
    public void deleteProgramTickets(Long id) {
        //1.查询该门票是否存在,不存在则抛出异常
        ProgramTicket programTicket = programTicketMapper.selectById(id);
        if(BeanUtil.isEmpty(programTicket)){
            throw new ProgramTicketNotFoundException(ExceptionConstant.PROGRAM_TICKET_NOT_FOUND);
        }
        //2.已开始出售则禁止修改
        if(programTicket.getRemainingCount().intValue() != programTicket.getTotalCount().intValue()){
            throw new ProgramTicketSellingRejectUpdateException(ExceptionConstant.PROGRAM_TICKET_SELLING_REJECT_UPDATE);
        }
        //3.删除门票
        programTicketMapper.deleteById(id);
        //4.将消息发送至交换机
        rabbitTemplate.convertAndSend(RabbitMqConstant.PROGRAM_DIRECT,
                RabbitMqConstant.PROGRAM_TICKET_DELETE_KEY,
                programTicket);
    }
}
